﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Threading;
using System.Management;
using System.Net;
using System.ServiceProcess;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

using RealTimePriceFetchService.BLL;
using RealTimePriceFetchService.Model;

using LanceZhang.StockLib;

namespace LanceZhang.DataDecompressService
{
    public class Program : ServiceBase
    {
        private static int WorkThreads = Convert.ToInt32(ConfigurationManager.AppSettings["WorkThreads"]);
        private static int SleepTime = Convert.ToInt32(ConfigurationManager.AppSettings["SleepTime"]);
        private static int CheckTime = Convert.ToInt32(ConfigurationManager.AppSettings["CheckTime"]);
        private static int BusyTime = Convert.ToInt32(ConfigurationManager.AppSettings["BusyTime"]);
        private static bool LogToFile = ConfigurationManager.AppSettings["LogToFile"] == "1" ? true : false;
        private static bool EnableZip = ConfigurationManager.AppSettings["EnableZip"] == "1" ? true : false;
        private static bool EnableClear = ConfigurationManager.AppSettings["EnableClear"] == "1" ? true : false;
        private static string ServiceRealName = ConfigurationManager.AppSettings["ServiceName"];
        private static string ServiceDisPlayName = ConfigurationManager.AppSettings["ServiceDisPlayName"];
        private static string ServiceDescription = ConfigurationManager.AppSettings["ServiceDescription"];

        private static int FromHour = Convert.ToInt32(ConfigurationManager.AppSettings["FromHour"]);
        private static int ToHour = Convert.ToInt32(ConfigurationManager.AppSettings["ToHour"]);

        private static object lockobj = new object();

        private static string IP = GetIPAddress();
        private static string MAC = GetMacAddress();

        //服务所在路径
        private static string ServicePath = Application.ExecutablePath;
        private static string ServiceDirectory = Path.GetDirectoryName(ServicePath);

        //单线程
        private static Thread t;

        //公共StringBuilder
        private static StringBuilder sb = new StringBuilder();

        //股票查询字符串列表
        private static List<string> querylist = new List<string>();

        //调试模式开关
        private static int Debug = 0;

        //服务是否停止开关
        private static bool Stopped = false;

        private static bool CanStopped = false;

        //线程状态字典
        private static Dictionary<string, bool> DicStatus = new Dictionary<string, bool>();

        //业务逻辑对象
        private static StockTransferQueueBLL bllqueue = new StockTransferQueueBLL();
        private static StockTransferSubQueueBLL bllsubqueue = new StockTransferSubQueueBLL();

        //业务逻辑实体
        private static List<StockTransferSubQueueModel> submodlist;
        private static StockTransferQueueModel mod;
        private static StockTransferSubQueueModel submod;

        //删除线程
        private static Thread threadCheck;
        //状态线程
        private static Thread threadStatus;

        //时间标记
        private static DateTime t2100;
        private static DateTime t2330;


        #region 应用程序初始化
        private static void InitilizeCompoment()
        {
            Output("开始初始化", true);
            if (Debug == 1)
            {
                Console.Title = ServiceDisPlayName;
            }

            if (WorkThreads > 1)
            {
                WorkThreads = 1;
            }

            if (WorkThreads < 1)
            {
                WorkThreads = 1;
            }

            Output("IP：" + IP, ConsoleColor.Green, true);
            Output("MAC：" + MAC, ConsoleColor.Green, true);
            Output("开始处理数据", ConsoleColor.Green, true);


            t = new Thread(DecompressData);
            t.IsBackground = false;
            t.Start();

            //开启状态线程
            threadCheck = new Thread(CheckStatus);
            threadCheck.Start();

            //开启状态线程
            threadStatus = new Thread(TimeStatus);
            threadStatus.Start();

            if (Debug == 1)
            {
                Console.ReadLine();
                Output("启动完成", true);
            }
        }


        #endregion

        #region 数据处理逻辑

        private static void DecompressData()
        {
            char[] c = { ';' };
            string[] results;

            while (true)
            {
                if (Stopped)
                {
                    CanStopped = true;

                    break;
                }

                try
                {
                    mod = bllqueue.GetTopModel();
                    if (mod == null)
                    {
                        Output("当前没有待处理的数据", ConsoleColor.Yellow, true);
                        Thread.Sleep(CheckTime);
                        continue;
                    }
                    Output("开始处理1数据", ConsoleColor.Blue, true);
                }
                catch (Exception ee)
                {
                    Output("获取数据时发生错误：" + ee.Message, ConsoleColor.Red, true);
                }                

                if (EnableZip)
                {
                    results = Compress.UnzipString(mod.RealTimePrice).Split(c);
                }
                else
                {
                    results = mod.RealTimePrice.Split(c);
                }

                submodlist = new List<StockTransferSubQueueModel>();

                foreach (string s in results)
                {
                    submod = new StockTransferSubQueueModel();
                    submod.RealTimeInfo = s;
                    submodlist.Add(submod);
                }

                foreach (StockTransferSubQueueModel m in submodlist)
                {
                    try
                    {
                        if (m.RealTimeInfo.Trim() == string.Empty)
                        {
                            continue;
                        }

                        bllsubqueue.Add(m);
                    }
                    catch (Exception e)
                    {
                        Output("插入数据时发生错误：" + e.Message, ConsoleColor.Red, true);
                    }
                }

                mod.HasCopied = true;

                try
                {
                    bllqueue.Update(mod);
                }
                catch (Exception eee)
                {
                    Output("更新数据时发生错误：" + eee.Message, ConsoleColor.Red, true);
                }

                Thread.Sleep(SleepTime);
            }
        }

        private static void CheckStatus()
        {
            if (!EnableClear)
            {
                return;
            }

            while (true)
            {
                if (Stopped)
                {
                    CanStopped = true;

                    break;
                }

                try
                {
                    bllqueue.Clear();
                    Output("清理了一批数据...", true);
                }
                catch (Exception e)
                {
                    Output("删除数据时发生错误：" + e.Message, ConsoleColor.Red, true);
                }

                Thread.Sleep(CheckTime);
            }
        }

        #endregion

        #region 应用程序入口
        static void Main(string[] args)
        {
            Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(Program_UnhandledException);
            Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

            bool exists = ServiceControl.CheckService(ServiceRealName);

            if (args.Length == 0)
            {
                ServiceBase.Run(new ServiceBase[] { new Program() });
            }
            else
            {
                string parm = args[0].ToLower();

                switch (parm)
                {
                    case "-debug":
                    case "/debug":

                        Debug = 1;

                        if (exists)
                        {
                            ServiceControllerStatus status = ServiceControl.GetServiceStatus(ServiceRealName);

                            if (status != ServiceControllerStatus.Stopped)
                            {
                                Console.WriteLine(GetDateTime() + ServiceRealName + " 服务正在运行，无法进入调试状态。请先停止该服务");
                                Console.WriteLine(GetDateTime() + "请关闭本窗体");
                                Console.ReadLine();
                            }
                            else
                            {
                                InitilizeCompoment();
                            }
                        }
                        else
                        {
                            InitilizeCompoment();
                        }


                        break;

                    case "-install":
                    case "-setup":
                    case "/install":
                    case "/setup":

                        if (exists)
                        {
                            Console.WriteLine(GetDateTime() + ServiceRealName + " 服务已经存在，如果您想升级服务，请先卸载该服务");
                            Console.WriteLine(GetDateTime() + "请关闭本窗体");
                            Console.ReadLine();
                        }
                        else
                        {
                            Console.WriteLine(GetDateTime() + ServicePath);

                            bool result = ServiceControl.InstallService(ServicePath, ServiceRealName, ServiceDisPlayName, ServiceDescription);

                            if (result)
                            {
                                Console.WriteLine(GetDateTime() + "服务安装成功");
                                Console.WriteLine(GetDateTime() + "正在启动服务...");

                                ServiceControl.StartService(ServiceRealName);

                                while (!(ServiceControl.GetServiceStatus(ServiceRealName) == ServiceControllerStatus.Running))
                                {
                                    Thread.Sleep(SleepTime);
                                }

                                Console.WriteLine(GetDateTime() + "服务已经启动");
                            }
                            else
                            {
                                Console.WriteLine(GetDateTime() + "服务安装失败");
                            }

                            Console.WriteLine(GetDateTime() + "请关闭本窗体");
                            Console.ReadLine();
                        }
                        break;

                    case "-uninstall":
                    case "-remove":
                    case "/uninstall":
                    case "/remove":

                        if (!exists)
                        {
                            Console.WriteLine(GetDateTime() + ServiceRealName + " 服务尚未安装");
                        }
                        else
                        {
                            bool result = ServiceControl.UnInstallService(ServiceRealName);

                            if (!result)
                            {
                                Console.WriteLine(GetDateTime() + "服务卸载失败");
                            }
                            else
                            {
                                Console.WriteLine(GetDateTime() + "服务卸载成功");
                            }
                        }

                        Console.WriteLine(GetDateTime() + "请关闭本窗体");
                        Console.ReadLine();

                        break;

                }

            }
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            Output("未处理A：" + e.Exception.Message, ConsoleColor.Red, true);
        }

        static void Program_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is System.Exception)
            {
                Output("未处理P：" + ((System.Exception)e.ExceptionObject).Message, ConsoleColor.Red, true);
            }

        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {

            }

            base.Dispose(disposing);
        }

        public Program()
        {
            base.ServiceName = ServiceRealName;
            base.AutoLog = true;
        }

        #endregion

        #region 初始化服务设置
        protected override void OnStart(string[] args)
        {
            InitilizeCompoment();
        }

        protected override void OnStop()
        {

            Stopped = true;

            try
            {
                if (WorkThreads == 1)
                {
                    while (!CanStopped)
                    {
                        Thread.Sleep(SleepTime);
                    }
                }
                else
                {
                    while (!AllStop())
                    {
                        Thread.Sleep(SleepTime);
                    }
                }
            }
            catch
            {
            }

        }

        /// <summary>
        /// 判断工作线程是否已经都停止了
        /// </summary>
        /// <returns></returns>
        private static bool AllStop()
        {
            try
            {
                lock (lockobj)
                {
                    foreach (bool value in DicStatus.Values)
                    {
                        if (!value)
                        {
                            return false;
                        }
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region 辅助逻辑

        #region 调试

        private static string GetDateTime()
        {
            return "[" + DateTime.Now.ToString("HH:mm:ss") + "] ";
        }

        private static void Output(string msg)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.WriteLine(GetDateTime() + msg);
                }
            }
        }

        private static void Output(string msg, bool log)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.WriteLine(GetDateTime() + msg);
                }

                if (log)
                {
                    if (LogToFile)
                    {
                        Log.WriteToFile(ServiceDirectory + @"\log_" + DateTime.Now.ToString("yyyyMMdd") + ".txt", GetDateTime() + msg);
                    }
                }
            }
        }

        private static void Output(string msg, ConsoleColor color)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.ForegroundColor = color;
                    Console.WriteLine(GetDateTime() + msg);
                    Console.ResetColor();
                }
            }
        }

        private static void Output(string msg, ConsoleColor color, bool log)
        {
            lock (lockobj)
            {
                if (Debug == 1)
                {
                    Console.ForegroundColor = color;
                    Console.WriteLine(GetDateTime() + msg);
                    Console.ResetColor();
                }

                if (log)
                {
                    if (LogToFile)
                    {
                        Log.WriteToFile(ServiceDirectory + @"\log_" + DateTime.Now.ToString("yyyyMMdd") + ".txt", GetDateTime() + msg);
                    }
                }
            }
        }

        #endregion

        #region 获得IP地址
        private static string GetIPAddress()
        {

            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());

            string ip = string.Empty;

            for (int i = 0; i < ips.Length; i++)
            {
                ip += ips[i].ToString() + ",";
            }

            if (ip != string.Empty)
            {
                ip = ip.Substring(0, ip.Length - 1);
            }

            return ip;

            /*
            string ip = string.Empty;
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                if ((bool)mo["IPEnabled"] == true)
                {
                    string[] ipaddresses = (string[])mo["IPAddress"];

                    for (int i = 0; i < ipaddresses.Length; i++)
                    {
                        ip += ipaddresses[i].ToString() + ",";
                    }
                }
            }

            if (ip != string.Empty)
            {
                ip = ip.Substring(0, ip.Length - 1);
            }

            return ip;
           */

        }
        #endregion

        #region 获得MAC
        private static string GetMacAddress()
        {
            ManagementClass adapters = new ManagementClass("Win32_NetworkAdapterConfiguration");
            string MACAddress = string.Empty;
            foreach (ManagementObject adapter in adapters.GetInstances())
            {
                if ((bool)adapter["IPEnabled"] == true)
                {
                    MACAddress = adapter.Properties["MACAddress"].Value.ToString();
                    MACAddress += ",";
                }
            }

            //去除最后一个,号
            if (MACAddress != string.Empty)
            {
                MACAddress = MACAddress.Substring(0, MACAddress.Length - 1);
            }

            return MACAddress;
        }
        #endregion

        #endregion

        #region 时间状态控制

        /// <summary>
        /// 接收状态
        /// </summary>
        private static void TimeStatus()
        {

            while (true)
            {
                if (isBusyTime())
                {
                    Output("目前系统繁忙，空闲时再执行", ConsoleColor.Green, true);
                    Stopped = true;
                }
                else
                {
                    if (Stopped)
                    {
                        Output("目前系统空闲，执行操作", ConsoleColor.Green, true);
                        Stopped = false;
                        InitilizeCompoment();
                    }
                }

                Thread.Sleep(BusyTime);
            }
        }

        /// <summary>
        /// 当前时间是否是繁忙时间
        /// </summary>
        /// <example>21：00~23：30处理数据</example>
        /// <returns></returns>
        private static bool isBusyTime()
        {
            t2100 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, FromHour, 0, 0);
            t2330 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, ToHour, 0, 0);

            if ((DateTime.Now > t2100) && (DateTime.Now < t2330))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        #endregion

    }
}
